﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NetalBase.Base;
using Castle.DynamicProxy;
using System.Diagnostics;
using System.Threading.Tasks;
using System.Threading;

namespace NetalBase
{
	public class AutomataContext : IDisposable
	{
		#region Fields
		IList<IAutomatonBase> _finalCheckEntities;
		bool _asyncWaiting4FinalState;
		#endregion

		#region Ctors
		public AutomataContext(bool asyncWaiting4FinalState = false)
		{
			_asyncWaiting4FinalState = asyncWaiting4FinalState;
			_finalCheckEntities = new List<IAutomatonBase>();
		}
		#endregion

		#region Public factory methods
		public TEntity Create<TEntity>() where TEntity : class, IAutomatonBase
		{
			var gen = new ProxyGenerator();
			var entity = gen.CreateClassProxy<TEntity>(new IAutomatonBaseInterceptor());
			Log.Logger.WriteCurrentState(entity);

			_finalCheckEntities.Add(entity);
			return entity;
		}
		#endregion

		#region IDisposable Members
		public void Dispose()
		{
			if (_asyncWaiting4FinalState)
			{
				var task = Task.Factory.StartNew(() =>
					{
						bool allInFinal = false;

						while (!allInFinal)
						{
							allInFinal = true;
							foreach (var entity in _finalCheckEntities)
							{
								entity.ProcessRelatedEvents();
								if (!entity.InFinalState)
								{
									allInFinal = false;
								}
							}

							if (!allInFinal)
								Thread.Sleep(100);
						}
					});
				task.Wait();
			}
			else
				foreach (var entity in _finalCheckEntities)
					Debug.Assert(entity.InFinalState);
		}
		#endregion
	}
}
